<?php
/**
 * Object representing a content type
 *
 * @package Concerto
 * @subpackage Models
 * @author Jason Raede <jason@torchdm.com>
 */
namespace application\models;
use application\utilities\Utility;
use application\models\DBObject;
class ContentType extends DBObject {

	/**
	 * ct_id
	 *
	 * @var int
	 */
	protected $id;
	
	/**
	 * ct_title
	 * 
	 * @var string
	 */
	protected $title;
	
	/**
	 * ct_plural
	 *
	 * @var string
	 */
	protected $plural;
	
	/**
	 * ct_permalink
	 *
	 * @var string
	 */
	protected $permalink;
	
	/**
	 * ct_search_appear
	 *
	 * @var bool
	 */
	protected $searchAppear = TRUE;
	
	/**
	 * ct_order_column
	 *
	 * @var string
	 */
	protected $orderColumn = 'content_title';
	
	/**
	 * ct_order_dir
	 *
	 * @var string
	 */
	protected $orderDirection = 'ASC';
	
	// System properties (defined as options, rather than on table. for better flexibility)
	
	/**
	 * @deprecated
	 */
	protected $allowSharing;
	
	/**
	 * Require approval when non-admins submit? (status goes to pending)
	 *
	 * @var bool
	 */
	protected $requireApproval = TRUE;
	
	/**
	 * Permalink structure for viewing single contents
	 *
	 * @var array
	 */
	protected $singlePermalinkStructure = array(
		array('name'=>'content_type'),
		array(
			'name'=>'content_identifier',
			'type'=>'title'
		)
	);
	
	/**
	 * @deprecated Moved to the permalink structure array
	 */
	protected $contentIdentifier = 'title';
	
	/**
	 * Permalink structure for viewing multiple contents
	 *
	 * @var array
	 */
	protected $browsingPermalinkStructure = array(
		array('name'=>'content_type')
	);
	
	/**
	 * Permalink structure for viewing contents with specific tags
	 *
	 * Generated on init because there are separate ones for each tag group
	 *
	 * @var array
	 */
	protected $tagPermalinkStructure = false;
	
	/**
	 * Can non-logged-in users submit content?
	 *
	 * @var bool
	 */
	protected $permNologgedSubmit = FALSE;
	
	/**
	 * Can logged-in users submit content?
	 *
	 * @var bool
	 */
	protected $permLoggedSubmit = TRUE;
	
	/**
	 * Contents of this type can have parents of these types
	 *
	 * @var array
	 */
	protected $allowedParents;
	
	/**
	 * MUST or CAN
	 *
	 * @var string
	 */
	protected $parentGate;
	
	/**
	 * Set this to TRUE if contents of this type are utility types or otherwise will not be displayed
	 * on their own templates
	 *
	 * @var bool
	 */
	protected $inaccessibleUrl = FALSE;
	
	/**
	 * Allow comments on contents of this type
	 *
	 * @var bool
	 */
	protected $allowComments;
	
	/**
	 * Allow ratings on contents of this type
	 *
	 * @var bool
	 */
	protected $allowRatings;
	
	/**
	 * How feedbacks are submitted. Can be "together" or "separate"
	 *
	 * @var string
	 */
	protected $feedbackMerge;
	
	/**
	 * How are ratings formatted? Can be 2, 5, 10, or 100
	 *
	 * var int
	 */
	protected $ratingsOutOf;
	
	/**
	 * @deprecated
	 */
	protected $ratingIconSelect;
	
	/**
	 * What are comments called? I.E. "replies", "messages", etc
	 *
	 * @var string
	 */
	protected $commentsName;
	
	/**
	 * Who can post feedback? Can be "anyone" or "logged_in"
	 *
	 * @var string
	 */
	protected $feedbackPermissions;
	
	/**
	 * Comments require approval before they appear?
	 *
	 * @var bool
	 */
	protected $commentsRequireApproval;
	
	/**
	 * Maximum length for comments
	 *
	 * @var int
	 */
	protected $commentsMaxLength;
	
	/**
	 * What are ratings called?
	 *
	 * @var string
	 */
	protected $ratingsName;
	
	/**
	 * Limit users to one rating per content?
	 *
	 * @var bool
	 */
	protected $ratingsLimit;
	
	/**
	 * Limit ratings to one comment per content?
	 *
	 * @var bool
	 */
	protected $commentsLimit;
	
	/**
	 * If ratingsOutOf is set to 2, you can set up/down text. I.E. "like"
	 *
	 * @var string
	 */
	protected $ratingUpText;
	
	/**
	 * If ratingsOutOf is set to 2, you can set up/down text. I.E. "dislike"
	 *
	 * @var string
	 */
	protected $ratingDownText;
	
	/**
	 * Allow basic HTML in comments?
	 *
	 * @var bool
	 */
	protected $commentsAllowBasicHtml;
	
	/**
	 * Number of words to display of content_content in the RSS feed
	 *
	 * @var int
	 */
	protected $numRssWords = 100;
	
	/**
	 * RSS is enabled for this content type?
	 *
	 * @var bool
	 */
	protected $enableRss = TRUE;
	
	/**
	 * Can be "excerpt" or "whole". If "excerpt", displays number 
	 * of words corresponding to $numRssWords
	 *
	 * @var string
	 */
	protected $rssDescription = 'excerpt';
	
	/**
	 * Number of items to display in the RSS feed
	 *
	 * @var int
	 */
	protected $numRssItems = 10;
	
	/**
	 * If $id is provided, initialize object with its database data
	 *
	 * @param int $id
	 */
	public function __construct($id = null) {
		if($id) {
			$row = DB()->getRow("SELECT * FROM `cn_content_types` WHERE `ct_id`='$id'");
			$this->id = $id;
			$this->title = $row->ct_title;
			$this->plural = $row->ct_plural;
			$this->permalink = $row->ct_permalink;
			$this->searchAppear = $row->ct_search_appear;
			
			$options = DB()->getResults("SELECT * FROM `cn_options` WHERE `option_name` LIKE 'c{$this->id}_%'");
			foreach($options as $option) {
				$propertyName = Utility::toCamelCase(substr($option->option_name, 3));
				if(in_array($propertyName, array('singlePermalinkStructure', 'browsingPermalinkStructure', 'tagPermalinkStructure')) && $option->option_value) {
					$this->$propertyName = unserialize($option->option_value);
				}
				elseif($option->option_value) {
					$this->$propertyName = $option->option_value;
				}
			}
			
			if(!is_array($this->singlePermalinkStructure)) {
				$this->singlePermalinkStructure = array(
					array('name'=>'content_type'),
					array(
						'name'=>'content_identifier',
						'type'=>'title'
					)
				);
			}
			if(!is_array($this->browsingPermalinkStructure)) {
				$this->browsingPermalinkStructure = array(
					array('name'=>'content_type')
				);
			}
			
			// Make the default tag permalink structure
			if(!$this->tagPermalinkStructure)  {
				$this->tagPermalinkStructure = array();
				$groups = DB()->getVarArray("SELECT `tag_id` FROM `cn_tags` WHERE `tag_content_type`='$id' AND `tag_type`='group'");
				foreach($groups as $group) {
					$this->tagPermalinkStructure[] = array('id'=>$group, 'structures'=>array(
						array('name'=>'content_type'),
						array('name'=>'tag_name')
					));
				}
			}
			
			
			$allowedParents =  unserialize($this->getOption('allowed_parents'));
			if(is_array($allowedParents)) $this->allowedParents = $allowedParents;
			else $this->allowedParents = array();
			
			if(!is_array($this->tinymceButtons)) {
				if($this->tinymceButtons)
					$this->tinymceButtons = unserialize($this->tinymceButtons);
				else
					$this->tinymceButtons = array();
			}
				
			
			
			
			
		}
	}
	
	
	/**
	 * Get an option associated with this content type
	 *
	 * @param string $option
	 * @return string
	 */
	protected function getOption($option) {
		return getOption('c'.$this->id.'_'.$option);
	}
	
	/**
	 * Set an option associated with this content type
	 *
	 * @param string $option
	 * @param sring $value
	 */
	protected function setOption($option, $value) {
		setOption('c'.$this->id.'_'.$option, $value);
	}
	
	/**
	 * Initialize the object with the data provided in $params
	 *
	 * @param array $params
	 */
	public function create($params) {
		if($params['title'] && $params['plural']) {
			foreach($params as $key=>$value) {
				$this->$key = $value;
			}
			// Generate the permalink
			$this->permalink = Utility::makeUrl($params['plural']);
		}
		else {
			Utility::triggerError('You must provide a title and a plural for a content type.');
		}
	}
	
	/**
	 * Updates all properties that are not set in cn_content_types
	 */
	protected function updateSystemProperties() {
		$dbOptions = array('id', 'title', 'plural', 'permalink', 'searchAppear');
		foreach($this as $key=>$value) {
			if(!in_array($key, $dbOptions)) {
				if($request = $_REQUEST[Utility::toSqlCase($key)]) {
					$this->$key = $request;
					$value = $request;
				}
				if(is_array($value)) {
					$value = serialize($value);
				}
				
				$this->setOption(Utility::toSqlCase($key), $value);
			}
		}
		
	}
	
	/**
	 * Create a new content type
	 */
	public function add() {
		global $concerto;
		// Check for duplicates
		if($concerto->DB->getCount("SELECT `ct_id` FROM `cn_content_types` WHERE `ct_title`='$this->name' OR `ct_plural`='$this->plural'")) {
			return array('status'=>'error', 'errors'=>array('There is already have a content type with that name.'));
		}
			
		$concerto->DB->insert('cn_content_types', array('ct_title'=>$this->title, 'ct_plural'=>$this->plural, 'ct_permalink'=>$this->permalink, 'ct_search_appear'=>$this->searchAppear));
		
		// Create the new table, add default fields
		$defaultFields = array(array('ID', 'content_id', 'ID', '1', '1'), array('Title', 'content_title', 'ShortText', '1', '1'), array('Permalink', 'content_permalink', 'Permalink', '0', '1'), array('Content', 'content_content', 'LongText', '0', '0'), array('Author', 'content_author', 'Author', '0', '1'), array('Status', 'content_status', 'Status', '0', '1'), array('Timestamp', 'content_timestamp', 'Timestamp', '0', '1'), array('Parent Content', 'content_parent', 'ParentContent', '0', '0'));
		$id = mysql_insert_id();
		foreach($defaultFields as $data) {
			$name = $data[0];
			$column = $data[1];
			$type = $data[2];
			$show = $data[3];
			$required = $data[4];
			
			mysql_query("INSERT INTO `cn_content_fields` (`cf_display_name`, `cf_column`, `cf_required`, `cf_content_type`, `cf_data_type`, `cf_show`) VALUES('$name', '$column', '$required', '$id', '$type', '$show')");
		}
		/** Create the table shell */
		
		$concerto->DB->query("CREATE TABLE IF NOT EXISTS `cn_content_type$id` (`c".$id."_id` bigint(20) NOT NULL, PRIMARY KEY(`c".$id."_id`))");
		
		// Store system properties
		$this->setId($id);
		$this->updateSystemProperties();
		
		
		return array('status'=>'success', 'id'=>$id);
	}
	
	/**
	 * Save the existing content type
	 *
	 * @return array DBObject status array.
	 */
	public function save() {
		global $concerto;
		// RSS options
		if(($this->numRssItems && !is_numeric($this->numRssItems)) || ($this->numRssWords && !is_numeric($this->numRssWords))) {
			return array('status'=>'error', 'errors'=>array('There is already have a content type with that name.'));
		}
		
		else {
			$concerto->DB->update('cn_content_types', 'ct_id', $this->id, array('ct_title'=>$this->title, 'ct_plural'=>$this->plural, 'ct_permalink'=>$this->permalink, 'ct_search_appear'=>$this->searchAppear, 'ct_order_column'=>$this->orderColumn, 'ct_order_direction'=>$this->orderDirection));
			$this->updateSystemProperties();
			return array('status'=>'success', 'id'=>$this->id);
		}

	}
	
	/**
	 * Delete the content type. This will also delete all fields and content of this type
	 *
	 * @return array DBObject status array.
	 */
	public function delete() {
		global $concerto;
		$concerto->DB->query("DELETE FROM `cn_content_types` WHERE `ct_id`='$this->id'");
		$concerto->DB->query("DELETE FROM `cn_content_fields` WHERE `cf_content_type`='$this->id'");
		$concerto->DB->query("DROP TABLE `cn_content_type{$this->id}`");
		$concerto->DB->query("DELETE FROM `cn_content` WHERE `content_type`='$this->id'");
		return array('status'=>'success');
	}
	
	/**
	 * Check if the string matches the "singular" value for a content type
	 *
	 * @param string $name
	 * @return int $type
	 */
	public static function matchesTypeSingular($name) {
		$name = ucwords(str_replace('-', ' ', $name));
		$type = DB()->getVar("SELECT `ct_id` FROM `cn_content_types` WHERE `ct_title`='$name'");
		return $type;
	}	
}

?>